<template>
  <div class="left-side">
    <h3>Pleat check you camera / microphone!</h3>
    <div class="buttons">
      <button @click="turnOnCamera" :class="{ 'button-on': isVideoOn }">
        Turn {{ isVideoOn ? "off" : "on" }} camera
      </button>
      <button @click="turnOnMicrophone" :class="{ 'button-on': isAudioOn }">
        Turn {{ isAudioOn ? "off" : "on" }} Microphone
      </button>
    </div>
    <h3>请输入appid 和 token</h3>
    <input placeholder="请输入appid"  v-model="appid" />
    <input placeholder="请输入token" v-model="token" />
    <h3>Please input the channel name</h3>
    <input v-model="channel" />
    <div class="buttons">
      <button @click="joinChannel" :class="{ 'button-on': isJoined }">
        Join Channel
      </button>
      <button @click="publishVideo" :class="{ 'button-on': isVideoPubed }">
        Publish Video
      </button>
      <button @click="publishAudio" :class="{ 'button-on': isAudioPubed }">
        Publish Audio
      </button>
      <button @click="leaveChannel">Leave Channel</button>
    </div>
    <!-- 显示频道状态 -->
    <div class="channel-status">
      <p>频道状态: 
        <span :class="{ 'status-joined': isJoined }">
          {{ isJoined ? '已加入频道: ' + channel : '未加入频道' }}
        </span>
      </p>
    </div>
    
    <!-- 显示用户列表 -->
    <div class="user-list" v-if="isJoined && userList.length > 0">
      <h4>频道用户列表:</h4>
      <div class="user-list-container">
        <div 
          v-for="user in userList" 
          :key="user.uid" 
          class="user-item"
          :class="{ 'local-user': user.isLocal }"
        >
          <div class="user-info">
            <span class="user-uid">{{ user.uid }}</span>
            <span v-if="user.isLocal" class="local-badge">我</span>
          </div>
          <div class="user-status">
            <span class="status-icon" :class="{ 'enabled': user.isVideoEnabled }">摄像头</span>
            <span class="status-icon" :class="{ 'enabled': user.isAudioEnabled }">麦克风</span>
          </div>
        </div>
      </div>
    </div>
    
    <!-- 显示事件日志 -->
    <div class="event-log">
      <h4>事件日志:</h4>
      <div class="log-container">
        <p v-for="(log, index) in eventLogs" :key="index" :class="log.type">
          [{{ log.timestamp }}] {{ log.message }}
        </p>
      </div>
    </div>
  </div>
  <div class="right-side">
    <div class="video-container" :class="{ 'expanded-mode': isExpandedRemoteUser }">
      <div 
        v-show="!isExpandedRemoteUser" 
        class="video-wrapper" 
        :class="{ 'local-video': true, 'hidden': isExpandedRemoteUser }">
        <video v-show="isVideoOn" id="camera-video"></video>
        <div class="video-label">我的视频</div>
      </div>
      
      <!-- 动态渲染远程用户的视频 -->
      <div 
        v-for="remoteUserItem in remoteUsers" 
        :key="remoteUserItem.uid"
        class="video-wrapper remote-video"
        :class="{ 'expanded': isExpandedRemoteUser === remoteUserItem.uid }"
        @click="toggleRemoteVideoExpand(remoteUserItem.uid)">
        <video 
          :id="'remote-video-' + remoteUserItem.uid" 
          v-show="remoteUserItem.isVideoSubed">
        </video>
        <div class="video-label">
          {{ isExpandedRemoteUser === remoteUserItem.uid ? '远程用户视频 (点击缩小)' : '远程用户视频 (点击放大)' }}
        </div>
        <div class="remote-user-info">
          用户ID: {{ remoteUserItem.uid }}
        </div>
      </div>
    </div>
    
    <!-- 远程视频控制按钮 -->
    <div v-if="isExpandedRemoteUser" class="remote-video-controls expanded-controls">
      <button @click.stop="toggleRemoteVideoExpand(isExpandedRemoteUser)" class="control-button">缩小</button>
      <button @click.stop="handleMuteRemoteVideo" class="control-button">
        {{ isRemoteVideoMuted ? '取消静音' : '静音' }}
      </button>
    </div>
    
    <div v-if="isJoined && remoteUsers.length === 0 && !isExpandedRemoteUser" class="waiting">
      You can shared channel {{ channel }} to others.....
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive } from "vue";
import type {
  IAgoraRTCClient,
  IAgoraRTCRemoteUser,
  ICameraVideoTrack,
  IMicrophoneAudioTrack,
  IRemoteAudioTrack,
} from "agora-rtc-sdk-ng";

import AgoraRTC from "agora-rtc-sdk-ng";

let track: ICameraVideoTrack;
let audioTrack: IMicrophoneAudioTrack;
let client: IAgoraRTCClient;

let appid = ref("");
let token = ref("");
let isJoined = ref(false);
let isAudioPubed = ref(false);
let isVideoPubed = ref(false);
let isAudioSubed = ref(false);
let isVideoSubed = ref(false);

let isVideoOn = ref(false);
let isAudioOn = ref(false);

// 添加远程用户信息
const remoteUsers = reactive<{uid: string, isVideoSubed: boolean}[]>([]);

// 添加用户列表
const userList = reactive<{uid: string, isVideoEnabled: boolean, isAudioEnabled: boolean, isLocal: boolean}[]>([]);

// 添加视频放大状态和控制
const isRemoteVideoExpanded = ref(false);
const isExpandedRemoteUser = ref<string | null>(null);
const isRemoteVideoMuted = ref(false);

// 事件日志数组
const eventLogs = reactive<{message: string, type: string, timestamp: string}[]>([]);

// 添加日志函数
function addLog(message: string, type: string = 'info') {
  const now = new Date();
  const timestamp = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}`;
  eventLogs.push({ message, type, timestamp });
  // 限制日志数量，只保留最近的20条
  if (eventLogs.length > 20) {
    eventLogs.shift();
  }
}

async function turnOnCamera() {
  isVideoOn.value = !isVideoOn.value;

  if (track) {
    const result = await track.setEnabled(!track.enabled);
    // 更新本地用户在用户列表中的视频状态
    const localUser = userList.find(u => u.isLocal);
    if (localUser) {
      localUser.isVideoEnabled = isVideoOn.value;
    }
    return result;
  }
  track = await AgoraRTC.createCameraVideoTrack();
  track.play("camera-video");
  // 更新本地用户在用户列表中的视频状态
  const localUser = userList.find(u => u.isLocal);
  if (localUser) {
    localUser.isVideoEnabled = true;
  }
  addLog("摄像头已" + (isVideoOn.value ? "开启" : "关闭"), "camera");
}

async function turnOnMicrophone() {
  isAudioOn.value = !isAudioOn.value;

  if (audioTrack) {
    const result = await audioTrack.setEnabled(!audioTrack.enabled);
    // 更新本地用户在用户列表中的音频状态
    const localUser = userList.find(u => u.isLocal);
    if (localUser) {
      localUser.isAudioEnabled = isAudioOn.value;
    }
    return result;
  }

  audioTrack = await AgoraRTC.createMicrophoneAudioTrack();
  // 更新本地用户在用户列表中的音频状态
  const localUser = userList.find(u => u.isLocal);
  if (localUser) {
    localUser.isAudioEnabled = true;
  }
  addLog("麦克风已" + (isAudioOn.value ? "开启" : "关闭"), "microphone");
}

const channel = ref("");
// you can apply appid follow the guide https://www.agora.io/en/blog/how-to-get-started-with-agora/
const APP_ID = "7a950ba3bcc949b1867564ac07d59dcb";
const token_ = "007eJxTYDhz8ITolbXdDst3yMiFNOY6szCW5ixhur2/rd+gTPrymbsKDOaJlqYGSYnGScnJliaWSYYWZuamZiaJyQbmKaaWKclJp/bdyGgIZGSw+7ickZEBAkF8ZgZDI2MGBgA4qB9k";

async function joinChannel() {
  if (!channel.value) {
    channel.value = "123";
  }
  //当用户已经在频道中，但想要重新加入（可能是因为网络断开、需要切换频道或刷新连接），
  //这个逻辑确保他们能够干净地离开后再重新加入。
  if (isJoined.value) {
    await leaveChannel();
  }

  if (!client) {
    client = AgoraRTC.createClient({
      mode: "rtc",
      codec: "vp8",
    });

    // 注册事件监听器
    setupEventListeners();
  }
  // 本地会触发 AgoraRTCClient.on("connection-state-change") 回调
  // 远端会触发 AgoraRTCClient.on("user-joined") 回调
  const uid = await client.join(appid.value?appid.value:APP_ID, channel.value?channel.value:"123", token.value ? token.value : token_);
  isJoined.value = true;
  
  // 添加本地用户到用户列表
  userList.push({
    uid: uid.toString(),
    isVideoEnabled: false,
    isAudioEnabled: false,
    isLocal: true
  });
  
  addLog(`成功加入频道: ${channel.value}`, "join");
}

// 设置事件监听器
function setupEventListeners() {
  client.on("user-published", onUserPublish);
  client.on("user-unpublished", onUserUnpublished);
  client.on("user-joined", onUserJoined);
  client.on("user-left", onUserLeft);
  client.on("connection-state-change", onConnectionStateChange);
  client.on("token-privilege-will-expire", onTokenPrivilegeWillExpire);
  client.on("exception", onException);
  // 添加本地用户事件监听
  client.on("stream-publication-changed", onStreamPublicationChanged);
}

async function leaveChannel() {
  isJoined.value = false;
  isAudioPubed.value = false;
  isVideoPubed.value = false;
  isAudioSubed.value = false;
  isVideoSubed.value = false;

  // 清除远程用户信息
  remoteUsers.length = 0;
  
  // 重置视频放大状态
  isExpandedRemoteUser.value = null;
  isRemoteVideoMuted.value = false;
  
  // 清空用户列表
  userList.length = 0;

  if (client) {
    //本地会触发 AgoraRTCClient.on("connection-state-change") 回调
    //远端会触发 AgoraRTCClient.on("user-left") 回调
    await client.leave();
    addLog("已离开频道", "leave");
  }
}

async function onUserPublish(
  user: IAgoraRTCRemoteUser,
  mediaType: "video" | "audio"
) {
  // 查找或创建远程用户记录
  let remoteUserItem = remoteUsers.find(u => u.uid === user.uid.toString());
  if (!remoteUserItem) {
    remoteUserItem = {
      uid: user.uid.toString(),
      isVideoSubed: false
    };
    remoteUsers.push(remoteUserItem);
  }
  
  // 更新用户列表中的用户状态
  const existingUser = userList.find(u => u.uid === user.uid.toString());
  if (!existingUser) {
    userList.push({
      uid: user.uid.toString(),
      isVideoEnabled: mediaType === "video",
      isAudioEnabled: mediaType === "audio",
      isLocal: false
    });
  } else {
    if (mediaType === "video") {
      existingUser.isVideoEnabled = true;
    }
    if (mediaType === "audio") {
      existingUser.isAudioEnabled = true;
    }
  }
  
  if (mediaType === "video") {
    const remoteTrack = await client.subscribe(user, mediaType);
    remoteTrack.play(`remote-video-${user.uid}`);
    remoteUserItem.isVideoSubed = true;
    addLog(`用户 ${user.uid} 发布了视频流`, "remote");
  }
  if (mediaType === "audio") {
    const remoteTrack = await client.subscribe(user, mediaType);
    remoteTrack.play();
    isAudioSubed.value = true;
    addLog(`用户 ${user.uid} 发布了音频流`, "remote");
  }
}

function onUserUnpublished(user: IAgoraRTCRemoteUser, mediaType: "video" | "audio") {
  addLog(`用户 ${user.uid} 取消发布 ${mediaType} 流`, "remote");
  
  const remoteUserItem = remoteUsers.find(u => u.uid === user.uid.toString());
  if (remoteUserItem && mediaType === "video") {
    remoteUserItem.isVideoSubed = false;
  }
  if (mediaType === "audio") {
    isAudioSubed.value = false;
  }
  
  // 更新用户列表中的用户状态
  const existingUser = userList.find(u => u.uid === user.uid.toString());
  if (existingUser) {
    if (mediaType === "video") {
      existingUser.isVideoEnabled = false;
    }
    if (mediaType === "audio") {
      existingUser.isAudioEnabled = false;
    }
  }
}

function onUserJoined(user: IAgoraRTCRemoteUser) {
  //通信场景下，该回调提示有远端用户加入了频道，并返回新加入用户的 ID；
  // 如果加入之前，已经有其他用户在频道中了，新加入的用户也会收到这些已有用户加入频道的回调。
  addLog(`用户 ${user.uid} 加入频道`, "user");
  
  // 添加用户到用户列表
  const existingUser = userList.find(u => u.uid === user.uid.toString());
  if (!existingUser) {
    userList.push({
      uid: user.uid.toString(),
      isVideoEnabled: false,
      isAudioEnabled: false,
      isLocal: false
    });
  }
}

function onUserLeft(user: IAgoraRTCRemoteUser) {
  addLog(`用户 ${user.uid} 离开频道`, "user");
  
  // 从远程用户列表中移除用户
  const remoteIndex = remoteUsers.findIndex(u => u.uid === user.uid.toString());
  if (remoteIndex !== -1) {
    remoteUsers.splice(remoteIndex, 1);
  }
  
  // 如果离开的用户是当前放大的用户，则取消放大
  if (isExpandedRemoteUser.value === user.uid.toString()) {
    isExpandedRemoteUser.value = null;
  }
  
  // 从用户列表中移除用户
  const index = userList.findIndex(u => u.uid === user.uid.toString());
  if (index !== -1) {
    userList.splice(index, 1);
  }
}

function onConnectionStateChange(curState: string, revState: string) {
  addLog(`连接状态变化: 从 ${revState} 变为 ${curState}`, "connection");
  // 如果连接断开，重置视频放大状态
  if (curState === "DISCONNECTED") {
    isExpandedRemoteUser.value = null;
    isRemoteVideoMuted.value = false;
  }
}

function onTokenPrivilegeWillExpire() {
  addLog("Token即将过期，请更新Token", "warning");
}

function onException(event: any) {
  addLog(`发生异常: ${JSON.stringify(event)}`, "error");
}

async function publishVideo() {
  if (!isVideoOn.value) {
    await turnOnCamera();
  }

  if (!isJoined.value) {
    await joinChannel();
  }
  //远端会触发 AgoraRTCClient.on("user-published") 回调
  await client.publish(track);
  isVideoPubed.value = true;
  
  // 更新本地用户在用户列表中的视频发布状态
  const localUser = userList.find(u => u.isLocal);
  if (localUser) {
    localUser.isVideoEnabled = true;
  }
  
  addLog(`本地用户${localUser?.uid}视频流发布成功`, "publish");
}

async function publishAudio() {
  if (!isAudioOn.value) {
    await turnOnMicrophone();
  }
  if (!isJoined.value) {
    await joinChannel();
  }

  await client.publish(audioTrack);
  isAudioPubed.value = true;
  
  // 更新本地用户在用户列表中的音频发布状态
  const localUser = userList.find(u => u.isLocal);
  if (localUser) {
    localUser.isAudioEnabled = true;
  }
  
  addLog("音频流发布成功", "publish");
}

// 修改切换远程视频放大状态的方法
function toggleRemoteVideoExpand(uid: string) {
  if (isExpandedRemoteUser.value === uid) {
    isExpandedRemoteUser.value = null;
  } else {
    isExpandedRemoteUser.value = uid;
  }
}

// 处理远程视频静音
function handleMuteRemoteVideo() {
  if (isVideoSubed.value) {
    isRemoteVideoMuted.value = !isRemoteVideoMuted.value;
    // 这里需要实现实际的静音逻辑，根据Agora SDK的API来处理
    addLog(`远程视频${isRemoteVideoMuted.value ? '已静音' : '已取消静音'}`, "remote");
  }
}

// 处理全屏
function handleFullscreen() {
  const videoElement = document.getElementById('remote-video');
  if (videoElement && videoElement.requestFullscreen) {
    videoElement.requestFullscreen().catch(err => {
      console.warn('全屏操作失败:', err);
    });
  } else if (videoElement && videoElement.webkitRequestFullscreen) {
    videoElement.webkitRequestFullscreen();
  } else if (videoElement && videoElement.msRequestFullscreen) {
    videoElement.msRequestFullscreen();
  }
  addLog('已进入全屏模式', 'info');
}

// 处理流发布状态变化
function onStreamPublicationChanged(user: IAgoraRTCRemoteUser | IAgoraRTCRemoteUser, mediaType: "video" | "audio", publicationState: "published" | "unpublished") {
  const uid = user.uid.toString();
  const existingUser = userList.find(u => u.uid === uid);
  
  if (existingUser) {
    if (mediaType === "video") {
      existingUser.isVideoEnabled = publicationState === "published";
    }
    if (mediaType === "audio") {
      existingUser.isAudioEnabled = publicationState === "published";
    }
  } else if (publicationState === "published") {
    // 如果用户不存在且正在发布流，则添加到列表中
    userList.push({
      uid: uid,
      isVideoEnabled: mediaType === "video",
      isAudioEnabled: mediaType === "audio",
      isLocal: uid === (client?.uid?.toString() || "")
    });
  }
}

</script>

<style>
.right-side {
  flex: 1;
  display: flex;
  flex-direction: column;
  background-color: #f0f0f0;
  padding: 10px;
}

.video-container {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 20px;
  justify-content: center;
  margin-bottom: 20px;
  position: relative;
}

.video-container.expanded-mode {
  display: block;
}

.video-wrapper {
  position: relative;
  min-width: 300px;
  aspect-ratio: 16/9;
  border: 2px solid #ddd;
  border-radius: 8px;
  overflow: hidden;
  cursor: pointer;
  transition: all 0.3s ease;
}

.video-wrapper.local-video.hidden {
  display: none;
}

.video-wrapper.remote-video.expanded {
  position: fixed;
  top: 10%;
  left: 50%;
  width: 80vw;
  height: 70vh;
  transform: translateX(-50%);
  z-index: 1000;
  background-color: #000;
  border: 2px solid #42b983;
  border-radius: 12px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
  transition: all 0.3s ease;
}

.video-wrapper.remote-video.expanded video {
  width: 100%;
  height: 100%;
  object-fit: contain;
  border-radius: 10px;
}

.video-wrapper video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  background-color: #333;
}

.video-wrapper.remote-video:not(.expanded) video {
  height: 100%;
  object-fit: cover;
}

.video-label {
  position: absolute;
  top: 10px;
  left: 10px;
  background-color: rgba(0, 0, 0, 0.7);
  color: white;
  padding: 5px 10px;
  border-radius: 4px;
  font-size: 14px;
  z-index: 10;
}

.remote-user-info {
  position: absolute;
  bottom: 10px;
  right: 10px;
  background-color: rgba(0, 0, 0, 0.7);
  color: white;
  padding: 5px 10px;
  border-radius: 4px;
  font-size: 14px;
  z-index: 10;
}

.remote-video-controls {
  display: flex;
  justify-content: center;
  gap: 15px;
  padding: 20px;
  background-color: rgba(0, 0, 0, 0.7);
  border-radius: 8px;
  margin: 10px auto;
  width: fit-content;
  z-index: 1001;
  position: fixed;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
}

.remote-video-controls.expanded-controls {
  display: flex;
  justify-content: center;
  gap: 15px;
  padding: 15px 25px;
  background-color: rgba(0, 0, 0, 0.7);
  border-radius: 30px;
  z-index: 1001;
  position: fixed;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
  transition: all 0.3s ease;
}

.control-button {
  padding: 10px 20px;
  background-color: #42b983;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 16px;
  transition: background-color 0.3s;
}

.control-button:hover {
  background-color: #359c6d;
}

.waiting {
  text-align: center;
  padding: 50px 20px;
  color: #666;
  font-size: 18px;
}

.channel-status {
  margin-top: 20px;
  padding: 10px;
  border-radius: 5px;
  background-color: #f5f5f5;
}

.channel-status p {
  margin: 0;
  font-weight: bold;
}

.status-joined {
  color: #42b983;
  font-weight: bold;
}

.user-list {
  margin-top: 20px;
  padding: 10px;
  border-radius: 5px;
  background-color: #f9f9f9;
}

.user-list h4 {
  margin-top: 0;
  margin-bottom: 10px;
}

.user-list-container {
  max-height: 200px;
  overflow-y: auto;
}

.user-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 12px;
  margin-bottom: 8px;
  background-color: #ffffff;
  border-radius: 4px;
  box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}

.user-item.local-user {
  border-left: 4px solid #42b983;
}

.user-info {
  display: flex;
  align-items: center;
  gap: 8px;
}

.user-uid {
  font-size: 14px;
  font-weight: 500;
}

.local-badge {
  background-color: #42b983;
  color: white;
  padding: 2px 6px;
  border-radius: 4px;
  font-size: 12px;
  font-weight: bold;
}

.user-status {
  display: flex;
  gap: 10px;
}

.status-icon {
  padding: 3px 6px;
  border-radius: 3px;
  font-size: 12px;
  background-color: #e0e0e0;
  color: #9e9e9e;
}

.status-icon.enabled {
  background-color: #42b983;
  color: white;
}

.event-log {
  margin-top: 20px;
  padding: 10px;
  border-radius: 5px;
  background-color: #f9f9f9;
  max-height: 300px;
  overflow-y: auto;
}

.event-log h4 {
  margin-top: 0;
  margin-bottom: 10px;
}

.log-container p {
  margin: 5px 0;
  padding: 2px 5px;
  border-radius: 3px;
  font-size: 14px;
  font-family: 'Courier New', monospace;
}

.log-container .info {
  background-color: #e3f2fd;
}

.log-container .camera {
  background-color: #e8f5e9;
}

.log-container .microphone {
  background-color: #f1f8e9;
}

.log-container .join {
  background-color: #e0f2f1;
}

.log-container .leave {
  background-color: #ffebee;
}

.log-container .remote {
  background-color: #f3e5f5;
}

.log-container .user {
  background-color: #fff3e0;
}

.log-container .connection {
  background-color: #eceff1;
}

.log-container .publish {
  background-color: #f1f8e9;
}

.log-container .warning {
  background-color: #fff8e1;
  color: #ff8f00;
}

.log-container .error {
  background-color: #ffebee;
  color: #c62828;
}
</style>
